<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Layout management in Ruby GTK</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Layout management, GTK, Ruby, programming, tutorial, Linux">
<meta name="description" content="In this part of teh Ruby GTK tutorial, we work with
layout management.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container2">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content2">


<a href="/" title="Home">Home</a>&nbsp;
<a href=".." title="Home">Contents</a>


<h1>Layout management</h1>


<p>
In this chapter we will show how to lay out our widgets in windows or dialogs. 
</p>

<div class="big_hor">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* big_horizontal */
google_ad_slot = "2904953388";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
When we design the GUI of our application, we decide what widgets we will use and how we will organize those
widgets in the application. To organize our widgets, we use specialized non visible widgets called 
<b>layout containers</b>. In this chapter, we will mention <code>Alignment</code>,
<code>Fixed</code>, <code>VBox</code> and <code>Table</code>.
</p>


<h2>Fixed</h2>

<p>
The <code>Fixed</code> container places child widgets at fixed positions and with fixed sizes.
This container performs no automatic layout management. In most applications, we don't use 
this container. There are some specialized areas, where we use it.
For example games, specialized applications that work with diagrams, resizable components
that can be moved (like a chart in a spreadsheet application), small educational examples.
</p>


<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby GTK tutorial
#
# In this program, we lay out widgets
# using absolute positioning
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'gtk2'


class RubyApp &lt; Gtk::Window

    def initialize
        super
    
        set_title "Fixed"
        signal_connect "destroy" do 
            Gtk.main_quit 
        end
        
        init_ui

        set_default_size 300, 280
        set_window_position Gtk::Window::POS_CENTER
        
        show_all
    end
    
    def init_ui
    
        modify_bg Gtk::STATE_NORMAL, Gdk::Color.new(6400, 6400, 6440)
               
        begin       
            bardejov = Gdk::Pixbuf.new "bardejov.jpg"
            rotunda = Gdk::Pixbuf.new "rotunda.jpg"
            mincol = Gdk::Pixbuf.new "mincol.jpg"
        rescue IOError => e
            puts e
            puts "cannot load images"
            exit
        end
        
        image1 = Gtk::Image.new bardejov
        image2 = Gtk::Image.new rotunda
        image3 = Gtk::Image.new mincol
        
        fixed = Gtk::Fixed.new
        
        fixed.put image1, 20, 20
        fixed.put image2, 40, 160
        fixed.put image3, 170, 50
  
        add fixed
        
    end
end

Gtk.init
    window = RubyApp.new
Gtk.main
</pre>

<p>
In our example, we show three small images on the window. We explicitely specify the x, y
coordinates, where we place these images. 
</p>

<pre class="explanation">
modify_bg Gtk::STATE_NORMAL, Gdk::Color.new(6400, 6400, 6440)
</pre>

<p>
For better visual experience, we change the background color to dark gray. 
</p>

<pre class="explanation">
bardejov = Gdk::Pixbuf.new "bardejov.jpg"
</pre>

<p>
We load the image from the disk to the <code>Pixbuf</code> object. 
</p>

<pre class="explanation">
image1 = Gtk::Image.new bardejov
image2 = Gtk::Image.new rotunda
image3 = Gtk::Image.new mincol
</pre>

<p>
The <code>Image</code> is a widget, that is used to display
images. It takes <code>Pixbuf</code> object in the constructor. 
</p>

<pre class="explanation">
fixed = Gtk::Fixed.new
</pre>

<p>
We create the <code>Fixed</code> container. 
</p>

<pre class="explanation">
fixed.put image1, 20, 20
</pre>

<p>
We place the first image at x=20, y=20 coordinates. 
</p>

<pre class="explanation">
 add fixed
</pre>

<p>
Finally, we add the <code>Fixed</code> container to the Window. 
</p>

<img src="/img/gui/rubygtk/fixed.png" alt="Fixed">
<div class="figure">Figure: Fixed</div>


<h2>Buttons</h2>

<p>
The <code>Alignment</code> container controls the alignment and 
the size of its child widget. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby GTK tutorial
#
# In this program, we position two buttons
# in the bottom right corner of the window.
# We use horizontal and vertical boxes.
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'gtk2'


class RubyApp &lt; Gtk::Window

    def initialize
        super
    
        set_title "Buttons"
        signal_connect "destroy" do 
            Gtk.main_quit 
        end
        
        init_ui

        set_default_size 260, 150
        set_window_position Gtk::Window::POS_CENTER
        
        show_all
    end
    
    def init_ui
    
        vbox = Gtk::VBox.new false, 5
        hbox = Gtk::HBox.new true, 3
        
        valign = Gtk::Alignment.new 0, 1, 0, 0
        vbox.pack_start valign
        
        ok = Gtk::Button.new "OK"
        ok.set_size_request 70, 30
        close = Gtk::Button.new "Close"
        
        hbox.add ok
        hbox.add close
        
        halign = Gtk::Alignment.new 1, 0, 0, 0
        halign.add hbox
        
        vbox.pack_start halign, false, false, 3

        add vbox
    end
end

Gtk.init
    window = RubyApp.new
Gtk.main
</pre>

<p>
In the code example, we place two buttons into the right bottom corner of the window.
To accomplish this, we use one horizontal box and one vertical box and two alignment containers. 
</p>

<pre class="explanation">
valign = Gtk::Alignment.new 0, 1, 0, 0
</pre>

<p>
This will put the child widget to the bottom. 
</p>

<pre class="explanation">
vbox.pack_start valign
</pre>

<p>
Here we place the <code>Alignment</code> widget into the vertical box.
</p>

<pre class="explanation">
hbox = Gtk::HBox.new true, 3 
...
ok = Gtk::Button.new "OK"
ok.set_size_request 70, 30
close = Gtk::Button.new "Close"

hbox.add ok
hbox.add close
</pre>

<p>
We create a horizontal box and put two buttons inside it. 
</p>

<pre class="explanation">
halign = Gtk::Alignment.new 1, 0, 0, 0
halign.add hbox

vbox.pack_start halign, false, false, 3
</pre>

<p>
This will create an alignment container that will place its child widget to the right.
We add the horizontal box into the alignment container and pack the alignment container
into the vertical box. We must keep in mind that the alignment container takes only one child widget. 
That's why we must use boxes. 
</p>


<img src="/img/gui/rubygtk/buttons.png" alt="Buttons">
<div class="figure">Figure: Buttons</div>


<h2>Calculator skeleton</h2>

<p>
The <code>Table</code> widget arranges widgets in rows and columns. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby GTK tutorial
#
# In this program we create a skeleton of
# a calculator. We use the Table widget. 
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'gtk2'


class RubyApp &lt; Gtk::Window

    def initialize
        super
    
        set_title "Calculator"
        signal_connect "destroy" do 
            Gtk.main_quit 
        end
        
        init_ui

        set_default_size 300, 250
        set_window_position Gtk::Window::POS_CENTER
        
        show_all
    end
    
    def init_ui
    
        vbox = Gtk::VBox.new false, 2
        
        mb = Gtk::MenuBar.new
        filemenu = Gtk::Menu.new
        file = Gtk::MenuItem.new "File"
        file.set_submenu filemenu
        mb.append file

        vbox.pack_start mb, false, false, 0

        table = Gtk::Table.new 5, 4, true

        table.attach Gtk::Button.new("Cls"), 0, 1, 0, 1
        table.attach Gtk::Button.new("Bck"), 1, 2, 0, 1
        table.attach Gtk::Label.new, 2, 3, 0, 1
        table.attach Gtk::Button.new("Close"), 3, 4, 0, 1

        table.attach Gtk::Button.new("7"), 0, 1, 1, 2
        table.attach Gtk::Button.new("8"), 1, 2, 1, 2
        table.attach Gtk::Button.new("9"), 2, 3, 1, 2
        table.attach Gtk::Button.new("/"), 3, 4, 1, 2

        table.attach Gtk::Button.new("4"), 0, 1, 2, 3
        table.attach Gtk::Button.new("5"), 1, 2, 2, 3
        table.attach Gtk::Button.new("6"), 2, 3, 2, 3
        table.attach Gtk::Button.new("*"), 3, 4, 2, 3

        table.attach Gtk::Button.new("1"), 0, 1, 3, 4
        table.attach Gtk::Button.new("2"), 1, 2, 3, 4
        table.attach Gtk::Button.new("3"), 2, 3, 3, 4
        table.attach Gtk::Button.new("-"), 3, 4, 3, 4

        table.attach Gtk::Button.new("0"), 0, 1, 4, 5
        table.attach Gtk::Button.new("."), 1, 2, 4, 5
        table.attach Gtk::Button.new("="), 2, 3, 4, 5
        table.attach Gtk::Button.new("+"), 3, 4, 4, 5

        vbox.pack_start Gtk::Entry.new, false, false, 0
        
        vbox.pack_end table, true, true, 0
        
        add vbox

    end
end

Gtk.init
    window = RubyApp.new
Gtk.main
</pre>

<p>
We use the <code>Table</code> widget to create a calculator skeleton.
</p>


<pre class="explanation">
table = Gtk::Table.new 5, 4, true
</pre>

<p>
We create a table widget with 5 rows and 4 columns. The third parameter
is the homogenous parameter. If set to true, all the widgets in the table
are of same size. The size of all widgets is equal to the largest 
widget in the table container. 
</p>

<pre class="explanation">
table.attach Gtk::Button.new("Cls"), 0, 1, 0, 1
</pre>

<p>
We attach a button to the table container. To the top-left cell of the table. 
The first two parameters are the left and right sides of the cell, the last two
parameters are the top and left sides of the cell. 
</p>

<pre class="explanation">
vbox.pack_end table, true, true, 0
</pre>

<p>
We pack the table widget into the vertical box. 
</p>

<img src="/img/gui/rubygtk/calculator.png" alt="Calculator skeleton">
<div class="figure">Figure: Calculator skeleton</div>


<h2>Windows</h2>

<p>
Next we will create a more advanced example. We show a window, that can be 
found in the JDeveloper IDE. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby GTK tutorial
#
# This is a more complicated layout example.
# We use Alignment and Table widgets. 
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'gtk2'


class RubyApp &lt; Gtk::Window

    def initialize
        super
    
        set_title "Windows"
        signal_connect "destroy" do 
            Gtk.main_quit 
        end
        
        init_ui

        set_default_size 300, 250
        set_window_position Gtk::Window::POS_CENTER
        
        show_all
    end
    
    def init_ui
    
        set_border_width 15
        
        table = Gtk::Table.new 8, 4, false
        table.set_column_spacings 3

        title = Gtk::Label.new "Windows"

        halign = Gtk::Alignment.new 0, 0, 0, 0
        halign.add title
        
        table.attach(halign, 0, 1, 0, 1, Gtk::FILL,
            Gtk::FILL, 0, 0)
            
        frame = Gtk::Frame.new
        table.attach(frame, 0, 2, 1, 3, Gtk::FILL | Gtk::EXPAND,
            Gtk::FILL | Gtk::EXPAND, 1, 1)

        activate = Gtk::Button.new "Activate"
        activate.set_size_request 50, 30
        table.attach(activate, 3, 4, 1, 2, Gtk::FILL,
            Gtk::SHRINK, 1, 1)
        
        valign = Gtk::Alignment.new 0, 0, 0, 0
        close = Gtk::Button.new "Close"
        close.set_size_request 70, 30
        valign.add close
        table.set_row_spacing 1, 3
        table.attach(valign, 3, 4, 2, 3, Gtk::FILL,
            Gtk::FILL | Gtk::EXPAND, 1, 1)
            
        halign2 = Gtk::Alignment.new 0, 1, 0, 0
        help = Gtk::Button.new "Help"
        help.set_size_request 70, 30
        halign2.add help
        table.set_row_spacing 3, 6
        table.attach(halign2, 0, 1, 4, 5, Gtk::FILL,
            Gtk::FILL, 0, 0)
        
        ok = Gtk::Button.new "OK"
        ok.set_size_request 70, 30
        table.attach(ok, 3, 4, 4, 5, Gtk::FILL,
            Gtk::FILL, 0, 0)
                          
        add table
    end
end

Gtk.init
    window = RubyApp.new
Gtk.main
</pre>

<p>
The code example shows, how we can create a similar window in Ruby GTK. 
</p>


<pre class="explanation">
table = Gtk::Table.new 8, 4, false
table.set_column_spacings 3
</pre>

<p>
The example is based on the <code>Table</code> container. There will
be 3px space between columns. 
</p>


<pre class="explanation">
title = Gtk::Label.new "Windows"

halign = Gtk::Alignment.new 0, 0, 0, 0
halign.add title

table.attach(halign, 0, 1, 0, 1, Gtk::FILL,
    Gtk::FILL, 0, 0)
</pre>

<p>
This code creates a label, that is aligned to the left. The label is placed 
in the first row of the Table container.
</p>

<pre class="explanation">
frame = Gtk::Frame.new
table.attach(frame, 0, 2, 1, 3, Gtk::FILL | Gtk::EXPAND,
    Gtk::FILL | Gtk::EXPAND, 1, 1)
</pre>

<p>
The frame view widget spans two rows and two columns. 
</p>

<pre class="explanation">
valign = Gtk::Alignment.new 0, 0, 0, 0
close = Gtk::Button.new "Close"
close.set_size_request 70, 30
valign.add close
table.set_row_spacing 1, 3
table.attach(valign, 3, 4, 2, 3, Gtk::FILL,
    Gtk::FILL | Gtk::EXPAND, 1, 1)
</pre>

<p>
We put the close button next to the frame widget into the fourth column. 
(we count from zero) We add the button into the alignment widget, 
so that we can align it to the top. 
</p>

<img src="/img/gui/rubygtk/windows.png" alt="Windows">
<div class="figure">Figure: Windows</div>

<p>
In this part of the Ruby GTK tutorial, we mentioned layout management of widgets. 
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified June 26, 2009  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>


